package com.yuyou.fn.analyze.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.yuyou.fn.analyze.entity.MainAccountTarget;
import com.yuyou.fn.analyze.mapper.MainAccountTargetMapper;
import com.yuyou.fn.analyze.service.IMainAccountTargetService;
import com.yuyou.fn.analyze.vo.MainAccountTargetDetailVo;
import com.yuyou.fn.analyze.vo.MainAccountTargetResultVo;
import com.yuyou.fn.analyze.vo.MainAccountTargetVo;
import com.yuyou.fn.analyze.vo.TargetTypeVo;
import com.yuyou.fn.common.service.ISiteConfigService;
import com.yuyou.fn.common.util.BeanUtils;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.common.util.Utils;
import com.yuyou.fn.educational.entity.BaseGrade;
import com.yuyou.fn.educational.entity.BaseSubject;
import com.yuyou.fn.educational.entity.Period;
import com.yuyou.fn.educational.service.IBaseGradeService;
import com.yuyou.fn.educational.service.IBaseSubjectService;
import com.yuyou.fn.educational.service.IPeriodService;
import com.yuyou.fn.platform.entity.AreaTeam;
import com.yuyou.fn.platform.entity.BusTeam;
import com.yuyou.fn.platform.service.IAreaTeamService;
import com.yuyou.fn.platform.service.IBusTeamService;
import com.yuyou.fn.settlement.service.IMainAccountService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 *
 * MainAccountTarget 表数据服务层接口实现类
 *
 */
@Service
public class MainAccountTargetServiceImpl extends SuperServiceImpl<MainAccountTargetMapper, MainAccountTarget,Long> implements IMainAccountTargetService {
    @Resource
    private IMainAccountService mainAccountService;

    @Resource
    private IBusTeamService busTeamService;

    @Resource
    private IAreaTeamService areaTeamService;

    @Resource
    private IPeriodService periodService;

    @Resource
    private ISiteConfigService siteConfigService;

    @Resource
    private IBaseGradeService baseGradeService;

    @Resource
    private IBaseSubjectService baseSubjectService;

    @Override
    @Transactional
    public void insertByList(Long mainAccountId,String year,String targetType,List<MainAccountTargetVo> mainAccountTargetVoList) {
        this.deleteByMainAccountId(mainAccountId,year,targetType);
        List<MainAccountTarget> mainAccountTargetList=new ArrayList<MainAccountTarget>();
        for (MainAccountTargetVo mainAccountTargetVo:mainAccountTargetVoList){
            MainAccountTarget mainAccountTarget=new MainAccountTarget();
            BeanUtils.copyProperties(mainAccountTarget,mainAccountTargetVo);
            mainAccountTarget.setCreateTime(TimeUtils.now());
            mainAccountTarget.setUpdateTime(TimeUtils.now());
            mainAccountTargetList.add(mainAccountTarget);
        }
        if (mainAccountTargetList.size()>0){
            this.insertBatch(mainAccountTargetList);
        }
    }

    @Override
    public void deleteByMainAccountId(Long mainAccountId, String year, String targetType) {
        if(mainAccountId == null || year == null || targetType == null ){
            throw new NullPointerException();
        }
        Example example=MainAccountTarget.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andEqualTo("mainAccountId",mainAccountId);
        criteria.andEqualTo("year",year);
        criteria.andEqualTo("targetType",targetType);
        this.deleteByExample(example);
    }


    @Override
    public List<MainAccountTarget> findListByMainAccountIdsAndPeriodIds(List<Long> mainAccountIdList, List<Long> periodIdList, String year, String targetType) {
        if (mainAccountIdList==null || mainAccountIdList.size()<=0){
            return Collections.EMPTY_LIST;
        }
        Example<MainAccountTarget> example=MainAccountTarget.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andIn("mainAccountId", mainAccountIdList);
        criteria.andIn("periodId",periodIdList);
        if (StringUtils.isNotEmpty(year)){
            criteria.andEqualTo("year",year);
        }
        if (targetType !=null){
            criteria.andEqualTo("targetType", targetType);
        }

        example.orderBy("mainAccountId");
        example.orderBy("periodNo");
        return this.findListByExample(example);
    }

    @Override
    public List<MainAccountTarget> findListByMainAccountIdsAndPeriodIdsLikeTypes(List<Long> mainAccountIdList, List<Long> periodIdList, String year,  String typeRightLike) {
        if (mainAccountIdList==null || mainAccountIdList.size()<=0  ){
            return Collections.EMPTY_LIST;
        }
        Example<MainAccountTarget> example=MainAccountTarget.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andIn("mainAccountId", mainAccountIdList);
        criteria.andIn("periodId",periodIdList);
        if (StringUtils.isNotEmpty(year)){
            criteria.andEqualTo("year",year);
        }
        if (StringUtils.isNotEmpty(typeRightLike)){
            criteria.andLike("targetType", "%"+typeRightLike);
        }

        example.orderBy("mainAccountId");
        example.orderBy("periodNo");
        return this.findListByExample(example);
    }

    @Override
    public List<MainAccountTarget> findListByMainAccountIdAndPeriodIds(Long mainAccountId, List<Long> periodIdList, String year, List<String> targetTypeList) {
        if (periodIdList==null || periodIdList.size()<=0 || targetTypeList==null || targetTypeList.size()<=0){
            return Collections.EMPTY_LIST;
        }
        Example<MainAccountTarget> example=MainAccountTarget.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andEqualTo("mainAccountId", mainAccountId);
        criteria.andIn("periodId",periodIdList);
        if (StringUtils.isNotEmpty(year)){
            criteria.andEqualTo("year",year);
        }
        criteria.andIn("targetType",targetTypeList);
        example.orderBy("targetType");
        example.orderBy("periodNo");
        return this.findListByExample(example);
    }

    @Override
    public  List<Map<String,Object>> findListByAreaTeamIdAndYear(Long areaTeamId, String year, String targetType) {
        List<Period> periodList=periodService.findByYearAndAreaTeamId(areaTeamId,year);
        List<Long> periodIdList=BeanUtils.toList(periodList,"periodId");
        if (periodIdList.size()<=0){
            return null;
        }
        List<Map<String,Object>> mapList=new ArrayList<Map<String,Object>>();
        AreaTeam areaTeam=areaTeamService.findById(areaTeamId);
        List<Long> mainAccountIdList=new ArrayList<Long>();
        mainAccountIdList.add(areaTeamId);
        List<BusTeam> busTeamList=busTeamService.findBusTeamByAreaTeamIds(Arrays.asList(areaTeamId));
        List<Long> busTeamIdList=BeanUtils.toList(busTeamList,"busTeamId");
        mainAccountIdList.addAll(busTeamIdList);
        HashMap<Long,String> map=new HashMap<Long,String>(mainAccountIdList.size());
        map.put(areaTeamId,areaTeam.getName());
        for (BusTeam busTeam:busTeamList){
            map.put(busTeam.getBusTeamId(),busTeam.getName());
        }
        List<MainAccountTarget> saveList=new ArrayList<MainAccountTarget>();
        List<MainAccountTarget> mainAccountTargetList=this.findListByMainAccountIdsAndPeriodIds(mainAccountIdList,periodIdList,year,targetType);
        Map<Long,List<MainAccountTarget>> mainAccountIdMap=BeanUtils.toGroup(mainAccountTargetList,"mainAccountId");
        for (Long mainAccountId:mainAccountIdList){
            if (mainAccountIdMap.containsKey(mainAccountId)){
                List<MainAccountTarget> tempList=mainAccountIdMap.get(mainAccountId);
                List<Long> havePeriodIds=BeanUtils.toList(tempList,"periodId");
                for (Period period:periodList){
                    if (!havePeriodIds.contains(period.getPeriodId())){
                        MainAccountTarget mainAccountTarget=new MainAccountTarget();
                        mainAccountTarget.setMainAccountId(mainAccountId);
                        mainAccountTarget.setYear(year);
                        mainAccountTarget.setTargetType(targetType);
                        mainAccountTarget.setCreateTime(TimeUtils.now());
                        mainAccountTarget.setUpdateTime(TimeUtils.now());
                        mainAccountTarget.setPeriodId(period.getPeriodId());
                        mainAccountTarget.setPeriodNo(period.getPeriodNo());
                        saveList.add(mainAccountTarget);
                    }
                }
            }else {
                for (Period period:periodList){
                    MainAccountTarget mainAccountTarget = new MainAccountTarget();
                    mainAccountTarget.setMainAccountId(mainAccountId);
                    mainAccountTarget.setYear(year);
                    mainAccountTarget.setTargetType(targetType);
                    mainAccountTarget.setCreateTime(TimeUtils.now());
                    mainAccountTarget.setUpdateTime(TimeUtils.now());
                    mainAccountTarget.setPeriodId(period.getPeriodId());
                    mainAccountTarget.setPeriodNo(period.getPeriodNo());
                    saveList.add(mainAccountTarget);
                }
            }
        }
        if (saveList.size()>0){
            this.insertBatch(saveList);
        }

        List<MainAccountTarget> resultList=this.findListByMainAccountIdsAndPeriodIds(mainAccountIdList,periodIdList,year,targetType);
        Map<Long,List<MainAccountTarget>> resultMap=BeanUtils.toGroup(resultList,"mainAccountId");
        Iterator<Map.Entry<Long, List<MainAccountTarget>>> entries = resultMap.entrySet().iterator();
        while (entries.hasNext()){
            Map<String,Object> result=new HashMap<String,Object>();
            Map.Entry<Long, List<MainAccountTarget>> entry = entries.next();
            Long mainAccountId=entry.getKey();
            List<MainAccountTarget> mainAccountTargets=entry.getValue();
            result.put("mainAccountId",mainAccountId);
            result.put("mainAccountName",map.get(mainAccountId));
            result.put("list",mainAccountTargets);
            result.put("year",year);
            result.put("targetType",targetType);
            mapList.add(result);
        }
        return mapList;

    }

    @Override
    public List<MainAccountTargetResultVo> findListByBusTeamIdAndYear(Long busTeamId, String year) {
        BusTeam busTeam=busTeamService.findById(busTeamId);
        List<Period> periodList=periodService.findByYearAndAreaTeamId(busTeam.getAreaTeamId(),year);
        String targetTypeJson = siteConfigService.getConfigValueFromCache("mainAccount_target_type");
        List<TargetTypeVo> targetTypeVoList = JSONArray.parseArray(targetTypeJson, TargetTypeVo.class);
        return this.toTargetListByTargeType(targetTypeVoList,periodList,busTeam.getBusTeamId(),busTeam.getName(),year);
    }


    @Override
    public List<MainAccountTargetResultVo> findAreaTeamGradeSubjectTarget(Long areaTeamId, String year) {
        List<BaseGrade> baseGradeList=baseGradeService.findAllOrderGrade();
        List<BaseSubject> baseSubjectList=baseSubjectService.findAllFromCache();
        List<Period> periodList=periodService.findByYearAndAreaTeamId(areaTeamId,year);
        AreaTeam areaTeam=areaTeamService.findById(areaTeamId);
        List<TargetTypeVo> targetTypeVoList=new ArrayList<>(baseGradeList.size()*baseSubjectList.size());
        for (BaseGrade baseGrade:baseGradeList){
            for (BaseSubject baseSubject:baseSubjectList){
                TargetTypeVo targetTypeVo=new TargetTypeVo();
                targetTypeVo.setGroupId(baseGrade.getGradeId());
                targetTypeVo.setGroupName(baseGrade.getGradeName());
                targetTypeVo.setTargetName(baseSubject.getSubjectName()+"预收");
                targetTypeVo.setType(1);
                targetTypeVo.setTargetType(baseGrade.getGradeId().toString()+"-"+baseSubject.getSubjectId().toString()+"-"+"99");
                targetTypeVoList.add(targetTypeVo);
            }
        }

        return this.toTargetListByTargeType(targetTypeVoList,periodList,areaTeam.getAreaTeamId(),areaTeam.getName(),year);
    }

    private  List<MainAccountTargetResultVo> toTargetListByTargeType(List<TargetTypeVo> targetTypeVoList, List<Period> periodList, Long mainAccountId, String mainAccountName, String year){
        List<String> targetTypeList=BeanUtils.toList(targetTypeVoList,"targetType");

        Map<String,TargetTypeVo> targetTypeVoMap=BeanUtils.toMap(targetTypeVoList,"targetType");
        List<Long> periodIdList=BeanUtils.toList(periodList,"periodId");
        if (periodIdList.size()<=0){
            return Collections.EMPTY_LIST;
        }
        List<MainAccountTarget> mainAccountTargetList=this.findListByMainAccountIdAndPeriodIds(mainAccountId,periodIdList,year,targetTypeList);
        Map<String,List<MainAccountTarget>> resultMap=BeanUtils.toGroup(mainAccountTargetList,"targetType");
        List<MainAccountTarget> saveList=new ArrayList<MainAccountTarget>();
        for (TargetTypeVo targetType:targetTypeVoList){
            if (resultMap.containsKey(targetType.getTargetType())){
                List<MainAccountTarget> tempList=resultMap.get(targetType.getTargetType());
                List<Long> havePeriodIds=BeanUtils.toList(tempList,"periodId");
                for (Period period:periodList){
                    if (!havePeriodIds.contains(period.getPeriodId())){
                        MainAccountTarget mainAccountTarget=new MainAccountTarget();
                        mainAccountTarget.setMainAccountId(mainAccountId);
                        mainAccountTarget.setYear(year);
                        mainAccountTarget.setTargetType(targetType.getTargetType());
                        mainAccountTarget.setCreateTime(TimeUtils.now());
                        mainAccountTarget.setUpdateTime(TimeUtils.now());
                        mainAccountTarget.setPeriodId(period.getPeriodId());
                        mainAccountTarget.setPeriodNo(period.getPeriodNo());
                        mainAccountTarget.setType(targetType.getType());
                        mainAccountTarget.setGroupId(targetType.getGroupId());
                        saveList.add(mainAccountTarget);
                    }
                }
            }else {
                for (Period period:periodList){
                    MainAccountTarget mainAccountTarget = new MainAccountTarget();
                    mainAccountTarget.setMainAccountId(mainAccountId);
                    mainAccountTarget.setYear(year);
                    mainAccountTarget.setTargetType(targetType.getTargetType());
                    mainAccountTarget.setCreateTime(TimeUtils.now());
                    mainAccountTarget.setUpdateTime(TimeUtils.now());
                    mainAccountTarget.setPeriodId(period.getPeriodId());
                    mainAccountTarget.setPeriodNo(period.getPeriodNo());
                    mainAccountTarget.setGroupId(targetType.getGroupId());
                    mainAccountTarget.setType(targetType.getType());
                    saveList.add(mainAccountTarget);
                }
            }
        }
        if (saveList.size()>0){
            this.insertBatch(saveList);
        }
        List<MainAccountTarget> resultList=this.findListByMainAccountIdAndPeriodIds(mainAccountId,periodIdList,year,targetTypeList);
        Map<Long,List<MainAccountTarget>> groupMap=BeanUtils.toGroup(resultList,"groupId");

        Iterator<Map.Entry<Long, List<MainAccountTarget>>> entries = groupMap.entrySet().iterator();
        List<MainAccountTargetResultVo> mainAccountTargetResultVos=new ArrayList<>(groupMap.size());

        while (entries.hasNext()){
            Map.Entry<Long, List<MainAccountTarget>> entry=entries.next();
            List<MainAccountTarget> mainAccountTargets=entry.getValue();
            if (mainAccountTargets==null){
                continue;
            }
            MainAccountTargetResultVo mainAccountTargetResultVo=new MainAccountTargetResultVo();
            Long groupId=entry.getKey();
            mainAccountTargetResultVo.setMainAccountId(mainAccountId);
            mainAccountTargetResultVo.setMainAccountName(mainAccountName);
            mainAccountTargetResultVo.setGroupId(groupId);
            Map<String,List<MainAccountTarget>> targetMap=BeanUtils.toGroup(mainAccountTargets,"targetType");
            Iterator<Map.Entry<String, List<MainAccountTarget>>> targetEntries = targetMap.entrySet().iterator();
            List<MainAccountTargetDetailVo> mainAccountTargetDetailVos=new ArrayList<MainAccountTargetDetailVo>();
            while (targetEntries.hasNext()){
                Map.Entry<String, List<MainAccountTarget>>  targetEntry= targetEntries.next();
                String targetType=targetEntry.getKey();
                MainAccountTargetDetailVo mainAccountTargetDetailVo=new MainAccountTargetDetailVo();
                mainAccountTargetDetailVo.setGroupId(groupId);
                mainAccountTargetDetailVo.setTargetType(targetType);
                List<MainAccountTarget> subs=targetEntry.getValue();

                mainAccountTargetDetailVo.setList(subs);
                mainAccountTargetDetailVo.setYear(year);

                TargetTypeVo targetTypeVo=targetTypeVoMap.get(targetType);
                if (targetTypeVo!=null){
                    mainAccountTargetDetailVo.setTargetName(targetTypeVo.getTargetName());
                    mainAccountTargetDetailVo.setGroupId(targetTypeVo.getGroupId());
                    mainAccountTargetDetailVo.setGroupName(targetTypeVo.getGroupName());
                    mainAccountTargetDetailVo.setType(targetTypeVo.getType());
                    mainAccountTargetResultVo.setGroupName(targetTypeVo.getGroupName());
                    mainAccountTargetResultVo.setType(targetTypeVo.getType());
                }
                mainAccountTargetDetailVos.add(mainAccountTargetDetailVo);
            }
            mainAccountTargetResultVo.setList(mainAccountTargetDetailVos);
            Collections.sort(mainAccountTargetDetailVos, new Comparator<MainAccountTargetDetailVo>() {
                public int compare(MainAccountTargetDetailVo o1,
                                   MainAccountTargetDetailVo o2) {
                    return (o1.getTargetType()).toString().compareTo(o2.getTargetType().toString());
                }
            });
            mainAccountTargetResultVos.add(mainAccountTargetResultVo);
        }
        Collections.sort(mainAccountTargetResultVos, new Comparator<MainAccountTargetResultVo>() {
            public int compare(MainAccountTargetResultVo o1,
                               MainAccountTargetResultVo o2) {
                Long groupId2=o2.getGroupId()==99l?-1l:o2.getGroupId();
                Long groupId1=o1.getGroupId()==99l?-1l:o1.getGroupId();
                return (groupId2).toString().compareTo(groupId1.toString());
            }
        });



        return mainAccountTargetResultVos;
    }

    @Override
    public List<MainAccountTarget> findListByMainAccountIdsAndPeriodIdAndTargetTypes(List<Long> mainAccountIdList, Long periodId, List<String> targetTypeList) {
        if (mainAccountIdList==null || mainAccountIdList.size()<=0 ||targetTypeList==null ||targetTypeList.size()<=0){
            return Collections.EMPTY_LIST;
        }
        Example<MainAccountTarget> example=MainAccountTarget.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andIn("mainAccountId", mainAccountIdList);
        criteria.andEqualTo("periodId",periodId);
        criteria.andIn("targetType", targetTypeList);
        example.orderBy("mainAccountId");
        example.orderBy("periodNo");
        return this.findListByExample(example);
    }

    @Override
    public List<MainAccountTarget> findByGroupId(Long busTeamId, List<Long> groupIds,Long periodId) {
        if (busTeamId==null  ||groupIds==null ||groupIds.size()<=0){
            return Collections.EMPTY_LIST;
        }

        Example<MainAccountTarget> example=MainAccountTarget.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andEqualTo("mainAccountId", busTeamId);
        criteria.andIn("groupId",groupIds);
        criteria.andEqualTo("periodId",periodId);
        return findListByExample(example);
    }

    @Override
    public List<MainAccountTarget> findByGroupId(List<Long> busTeamIds, List<Long> groupIds, List<Long> periodIds) {
        if (busTeamIds==null ||busTeamIds.size()<=0){
            return Collections.EMPTY_LIST;
        }
        Example<MainAccountTarget> example=MainAccountTarget.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andIn("mainAccountId",busTeamIds);
        if (Utils.checkListNotEmpty(groupIds)){
            criteria.andIn("groupId",groupIds);
        }
        if (Utils.checkListNotEmpty(periodIds)){
            criteria.andIn("periodId",periodIds);
        }
        return findListByExample(example);
    }

    @Override
    public List<MainAccountTarget> findListByMainAccountIdsAndPeriodIdsAndTargetTypes(List<Long> mainAccountIdList, List<Long> periodIds, List<String> targetTypeList) {
        if (mainAccountIdList==null || mainAccountIdList.size()<=0 ||targetTypeList==null ||targetTypeList.size()<=0 || Utils.checkListEmpty(periodIds)){
            return Collections.EMPTY_LIST;
        }
        Example<MainAccountTarget> example=MainAccountTarget.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andIn("mainAccountId", mainAccountIdList);
        criteria.andIn("periodId",periodIds);
        criteria.andIn("targetType", targetTypeList);
        example.orderBy("mainAccountId");
        example.orderBy("periodNo");
        return this.findListByExample(example);
    }
}